package com.gzc.just.play.last.war.sceneserver.repository;

import com.gzc.just.play.last.war.sceneserver.entity.Player;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * 玩家数据访问接口
 * 
 * 提供玩家相关的数据库操作方法
 * 作为Phase 4.3数据库持久化集成的一部分
 */
@Repository
public interface PlayerRepository extends JpaRepository<Player, Long>, JpaSpecificationExecutor<Player> {
    
    /**
     * 根据用户名查找玩家
     */
    Optional<Player> findByUsername(String username);
    
    /**
     * 根据昵称查找玩家
     */
    Optional<Player> findByNickname(String nickname);
    
    /**
     * 根据用户名或昵称查找玩家
     */
    Optional<Player> findByUsernameOrNickname(String username, String nickname);
    
    /**
     * 根据用户名和密码哈希查找玩家（用于登录）
     */
    Optional<Player> findByUsernameAndPasswordHash(String username, String passwordHash);
    
    /**
     * 查找在线玩家
     */
    List<Player> findByIsOnlineTrue();
    
    /**
     * 查找被封禁的玩家
     */
    List<Player> findByIsBannedTrue();
    
    /**
     * 查找当前被封禁的玩家
     */
    @Query("SELECT p FROM Player p WHERE p.isBanned = true AND (p.banEndTime IS NULL OR p.banEndTime > :now)")
    List<Player> findCurrentlyBannedPlayers(@Param("now") LocalDateTime now);
    
    /**
     * 根据等级范围查找玩家
     */
    Page<Player> findByLevelBetween(Integer minLevel, Integer maxLevel, Pageable pageable);
    
    /**
     * 查找VIP玩家
     */
    List<Player> findByVipLevelGreaterThan(Integer minVipLevel);
    
    /**
     * 根据创建时间范围查找玩家
     */
    List<Player> findByCreateTimeBetween(LocalDateTime startTime, LocalDateTime endTime);
    
    /**
     * 查找最近登录的玩家
     */
    List<Player> findByLastLoginTimeAfter(LocalDateTime time);
    
    /**
     * 统计在线玩家数量
     */
    long countByIsOnlineTrue();
    
    /**
     * 统计当前被封禁的玩家数量
     */
    @Query("SELECT COUNT(p) FROM Player p WHERE p.isBanned = true AND (p.banEndTime IS NULL OR p.banEndTime > :now)")
    long countCurrentlyBannedPlayers(@Param("now") LocalDateTime now);
    
    /**
     * 统计指定等级的玩家数量
     */
    long countByLevel(Integer level);
    
    /**
     * 统计VIP玩家数量
     */
    long countByVipLevelGreaterThan(Integer minVipLevel);
    
    /**
     * 查找等级排行榜
     */
    @Query("SELECT p FROM Player p WHERE p.level >= :minLevel ORDER BY p.level DESC, p.experience DESC")
    Page<Player> findLevelLeaderboard(@Param("minLevel") Integer minLevel, Pageable pageable);
    
    /**
     * 查找经验排行榜
     */
    @Query("SELECT p FROM Player p WHERE p.level = :level ORDER BY p.experience DESC")
    Page<Player> findExperienceLeaderboard(@Param("level") Integer level, Pageable pageable);
    
    /**
     * 查找最近登录但没有完成新手引导的玩家
     */
    @Query("SELECT p FROM Player p WHERE p.lastLoginTime > :time AND p.level = 1")
    List<Player> findNewPlayersWhoNeedTutorial(@Param("time") LocalDateTime time);
    
    /**
     * 更新玩家在线状态
     */
    @Modifying(clearAutomatically = true, flushAutomatically = true)
    @Query("UPDATE Player p SET p.isOnline = :isOnline, p.lastLoginTime = CASE WHEN :isOnline = true THEN :now ELSE p.lastLoginTime END, p.lastLogoutTime = CASE WHEN :isOnline = false THEN :now ELSE p.lastLogoutTime END WHERE p.playerId = :playerId")
    int updatePlayerOnlineStatus(@Param("playerId") Long playerId, @Param("isOnline") Boolean isOnline, @Param("now") LocalDateTime now);
    
    /**
     * 更新玩家等级和经验
     */
    @Modifying(clearAutomatically = true, flushAutomatically = true)
    @Query("UPDATE Player p SET p.level = :level, p.experience = :experience WHERE p.playerId = :playerId")
    int updatePlayerLevelAndExperience(@Param("playerId") Long playerId, @Param("level") Integer level, @Param("experience") Long experience);
    
    /**
     * 增加玩家经验
     */
    @Modifying(clearAutomatically = true, flushAutomatically = true)
    @Query("UPDATE Player p SET p.experience = p.experience + :experience, p.level = :level WHERE p.playerId = :playerId")
    int addPlayerExperience(@Param("playerId") Long playerId, @Param("experience") Long experience, @Param("level") Integer level);
    
    /**
     * 解除玩家封禁
     */
    @Modifying(clearAutomatically = true, flushAutomatically = true)
    @Query("UPDATE Player p SET p.isBanned = false, p.banReason = NULL, p.banEndTime = NULL WHERE p.playerId = :playerId")
    int unbanPlayer(@Param("playerId") Long playerId);
    
    /**
     * 更新玩家最后登录时间和登录次数
     */
    @Modifying(clearAutomatically = true, flushAutomatically = true)
    @Query("UPDATE Player p SET p.lastLoginTime = :now, p.loginCount = p.loginCount + 1 WHERE p.playerId = :playerId")
    int updateLoginInfo(@Param("playerId") Long playerId, @Param("now") LocalDateTime now);
    
    /**
     * 批量更新玩家最后登出时间
     */
    @Modifying(clearAutomatically = true, flushAutomatically = true)
    @Query("UPDATE Player p SET p.isOnline = false, p.lastLogoutTime = :now WHERE p.isOnline = true")
    int batchUpdateLastLogoutTime(@Param("now") LocalDateTime now);
}